package com.linesum.code.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.linesum.code.domain.dao.UserDao;
import com.linesum.code.domain.entity.UserEntity;
import com.linesum.code.dto.UserSearchDto;
import com.linesum.code.service.UserService;

/**
 * 用户服务实现类
 * @author chenzf
 *
 */
@SuppressWarnings("static-method")
@Service
@CacheConfig(cacheNames = "user")
public class UserServiceImpl implements UserService {
	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private UserDao userDao;

	@Override
	@Transactional(rollbackFor = Exception.class)
	//使用参数#p代替(如：参数1#p0参数2#p1) 或者使用参数名#user
	//@CachePut(key = "#p0.id")
	@CachePut(key = "#user.id")
	public UserEntity save(UserEntity user) {
		UserEntity save = userDao.save(user);
		if (save != null) {
			throw new RuntimeException("测试事物");
		}
		return save;
	}

	@Override
	public Page<UserEntity> findAll(final Pageable pageable, final UserSearchDto dto) {
		Page<UserEntity> page = userDao.findAll(new Specification<UserEntity>() {
			@Override
			public Predicate toPredicate(Root<UserEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> where = Lists.newArrayList();
				Path<String> username = root.get("username");
				Path<String> mobile = root.get("mobile");
				Path<Integer> status = root.get("status");
				Path<Date> lastModifyTime = root.get("lastModifyTime");
				Path<String> lastModifyBy = root.get("lastModifyBy");

				if (StringUtils.isNotBlank(dto.getUserName())) {
					where.add(cb.and(cb.like(username, "%" + dto.getUserName() + "%")));
				}
				if (StringUtils.isNotBlank(dto.getMobile())) {
					where.add(cb.and(cb.like(mobile, dto.getMobile())));
				}
				if (dto.getStatus() != null) {
					where.add(cb.and(cb.equal(status, dto.getStatus())));
				}
				if (StringUtils.isNotBlank(dto.getTimeBegin()) || StringUtils.isNotBlank(dto.getTimeOver())) {
					Date timeBegin = transformTime(dto.getTimeBegin());
					Date timeOver = transformTime(dto.getTimeOver());
					if (timeOver != null && timeBegin != null) {
						where.add(cb.and(cb.between(lastModifyTime, timeBegin, timeOver)));
					} else if (timeBegin != null) {
						where.add(cb.and(cb.greaterThanOrEqualTo(lastModifyTime, timeBegin)));
					} else if (timeOver != null) {
						where.add(cb.and(cb.lessThanOrEqualTo(lastModifyTime, timeOver)));
					}
				}
				if (StringUtils.isNotBlank(dto.getLastModifyBy())) {
					where.add(cb.like(lastModifyBy, "%" + dto.getLastModifyBy() + "%"));
				}
				query.where(where.toArray(new Predicate[] {}));
				return null;
			}
		}, pageable);
		return page;
	}

	public Date transformTime(String time) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//小写的mm表示的是分钟  
		Date date = null;
		try {
			date = sdf.parse(time);
		} catch (ParseException e) {
			logger.error("用户搜索时间格式转换出错, time={} , exception={} ", time, e);
			date = null;
		}
		return date;
	}

	@Override
	//使用参数#p代替(如：参数1#p0参数2#p1) 或者使用参数名#userId
	//@Cacheable(key = "#p0")
	@Cacheable(key = "#userId")
	public UserEntity getUser(Long userId) {
		return userDao.findOne(userId);
	}

	@Override
	public UserEntity getUser(String loginNameOrmobile) {
		if (isMobile(loginNameOrmobile)) {
			return userDao.findByMobile(loginNameOrmobile);
		} else {
			return userDao.findByLoginName(loginNameOrmobile);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteUser(Long userId) {
		userDao.delete(userId);
	}

	/**
	 * 验证手机号码
	 * @param param
	 * @return
	 */
	private boolean isMobile(String param) {
		try {
			Long.valueOf(param.trim());
			return true;
		} catch (Exception e) {
			return false;
		}
	}
}
